有一天,小明來問我這個問題:
如何使用Dotnet Core DI注入Quartz Job所需的依賴物件?
首先,我們創建一個Quartz Job對象,一個簡單的Quartz Job示例代碼如下:
public class MyJob : IJob
{
public MyJob(IMyLogger logger)
{
//Blah...
}
void Execute(JobExecutionContext context)
{
//Blah...
}
}
通常我們是按照下面方式開始建立Quartz Job,
var job = JobBuilder.Create<MyJob>()
.WithIdentity("myJob")
.Build();
但是上面的程式碼沒辦法從Dotnet Core DI 自動注入, 幸運的是Quartz 提供了IJobFactory 介面接口, 它允許我們創建自定義的JobFactory 類別.
現在我們創建一個MyJobFactory 自定義JobFactory 類別並實現IJobFactory ,如下所示:
public class MyJobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public MyJobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle,
IScheduler scheduler)
{
return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob;
}
public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
disposable?.Dispose();
}
}
接下來, 我們創建自己的Schedule 物件, 如下所示:
public class MyScheduler : IMyScheduler
{
StdSchedulerFactory _scheduler;
public MyScheduler(IJobFactory myJobFactory)
{
_scheduler = new StdSchedulerFactory()
.GetScheduler()
.Result;
_scheduler.JobFactory = myJobFactory;
}
public void Start()
{
var job = CreateJob<MyJob>();
var trigger = TriggerBuilder.Create()
.StartNow()
.WithCronSchedule("0/10 ...")
.Build();
_scheduler.ScheduleJob(job, trigger);
_scheduler.Start();
}
private IJobDetail CreateJob<T>() where T : IJob
{
return JobBuilder.Create<T>()
.WithIdentity(typeof(T).Name)
.Build();
}
}
注意上面的程式碼, 關鍵點在於這個地方
_scheduler.JobFactory = myJobFactory;
Quartz JobBuilder.Create() 方法將通過 myJobFactory 實例生成Job 物件.
然後我們在 Dotnet Project Startup.cs 檔案中, 註冊所有必需的類別.
public void ConfigureServices(IServiceCollection services)
{
//Blah....
services.AddTransient<IMyLogger, MyLogger>();
services.AddTransient<IJobFactory, MyJobFactory>();
services.AddSingleton<IMyScheduler, MyScheduler>();
}
為了讓程式碼更容易閱讀, 我們建立了一個擴充方法
public static class MyQuartzExtension
{
public static void UseQuartz(this IApplicationBuilder app)
{
var scheduler = app.ApplicationServices
.GetService<IMyScheduler>();
scheduler.Start();
}
}
最後我們在 startup.cs 中呼叫 UseQuartz()
public void Configure(IApplicationBuilder app,
IHostingEnvironment env)
{
//Blah...
app.UseQuartz();
}
現在我們完成了這個偉大的任務 "DI 自動注入 Quartz Job 所需的依賴物件" !!